package com.ts.comm;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import java.io.IOException;
import java.security.MessageDigest;

/**
 * 复杂的加密解密类
 * Created by xhc on 2017/5/2.
 */
public class SysEncrypt {



    /**
     * MD5加密字符串，并返回加密过的字符串
     *
     * @param str 需要加密的字符串
     * @return String
     */
    public static String MD5(String str) throws Exception {
        str = (str == null) ? "" : str;
        byte[] by = str.getBytes();
        String md5Str = "";

        MessageDigest md = MessageDigest.getInstance("MD5");
        md5Str = SysString.byte2hex(md.digest(by));

        return md5Str;
    }

    /**
     * SHA-1加密字符串，并返回加密过的字符串
     *
     * @param str 需要加密的字符串
     * @return String
     */
    public static String SHA1(String str) throws Exception {
        byte[] by = str.getBytes();
        String shaStr = "";

        MessageDigest md = MessageDigest.getInstance("SHA-1");
        shaStr = SysString.byte2hex(md.digest(by));

        return shaStr;
    }
    /**
     * 字符串加密  base64加密方式 可逆  解密调用desEncrypt
     *
     * @param str
     * @return
     */
    public static String encrypt(String str) {
        if (SysString.isEmpty(str))
            return "";

        String sRet = "";

        BASE64Encoder be = new BASE64Encoder();
        sRet = be.encodeBuffer(str.getBytes());
        sRet = sRet.replace("=", "@").replace("\r\n", "");
        return sRet;
    }

    /**
     * 对字符串解密
     *
     * @param sValue
     * @return
     */
    public static String desEncrypt(String sValue) {
        String sRet = "";
        if (!SysString.isEmpty(sValue)) {
            try {
                BASE64Decoder bd = new BASE64Decoder();
                sValue = sValue.replace("@", "=");
                byte[] by = bd.decodeBuffer(sValue);
                sRet = new String(by, "UTF-8");
            } catch (IOException e) {
                sRet = "";
            }

        }
        return sRet;
    }

    /**
     * 查账软件C6加密算法
     *
     * @param str 要加密字符串
     * @return 加密完成的字符串
     */
    public static String c6EnCode(String str) {
        String sRet = "", s = "";
        int iLen = 0;
        if (!SysString.isEmpty(str)) {
            iLen = str.length();
            if (iLen % 2 != 0) {
                str = str + String.valueOf((char) 0);
                iLen += 1;
            }
            char[] ca = str.toCharArray();

            for (int i = 0; i < iLen / 2; i++) // step1 >|>
            {
                ex(ca, i, iLen / 2 + i);
            }
            for (int i = 0; i < iLen / 2; i++)// step2 >|<
            {
                ex(ca, i, iLen - i - 1);
            }
            for (int i = 0; i < iLen / 2; i++)// step3 >>
            {
                ex(ca, i * 2, i * 2 + 1);
            }

            for (int i = 0; i < ca.length; i++) {
                s = Integer.toHexString(ca[i]);
                if (s.length() < 4) {
                    sRet += SysString.repeatStr(4 - s.length(), "0") + s;
                } else {
                    sRet += s;
                }
            }
        }
        return sRet.toUpperCase();
    }

    private static void ex(char[] ca, int iBeg, int iEnd) {

        char r1, r2;

        char b = ca[iBeg];
        char e = ca[iEnd];

        int bh = (b >>> 8);// 取高位
        int bl = (b & 0xff);// 取底位

        int eh = (e >>> 8);// 取高位
        int el = (e & 0xff);// 取底位

        b = (char) (bitMove(bh, 1) << 8 | bitMove(bl, 4));
        e = (char) (bitMove(eh, 3) << 8 | bitMove(el, 2));

        // b=0x1234 e=0xABCD
        // r1 = 0xC41B
        // r2 = 0x2DA3

        r1 = (char) ((e & 0xf0) << 8 | (b & 0xf) << 8 | (b & 0xf000) >>> 8 | (e & 0xf00) >>> 8);
        r2 = (char) ((b & 0xf00) << 4 | (e & 0xf) << 8 | (e & 0xf000) >>> 8 | (b & 0xf0) >>> 4);

        ca[iBeg] = r1;
        ca[iEnd] = r2;
    }

    private static int bitMove(int iBit, int iStep) {
        int iRet = 0;
        if (iStep == 0) {
            iRet = iBit;
        } else if (iStep > 0) // <<<
        {
            iRet = ((iBit << iStep) & 0xff) | (iBit >>> (8 - iStep));
        } else if (iStep < 0) // >>>
        {
            iRet = (iBit >>> iStep) | ((iBit << (8 - iStep)) & 0xff);
        }
        return iRet;

    }
}
